﻿#include "pch.h"
#if _QG_ENABLE_WIDGET
#include "qgp/qgach.h"
#include "qgp/qgaud.h"
#include "qgp/qguwgs.h"

//////////////////////////////////////////////////////////////////////////
// 목록
KIMPL_SUBCLASS(qwList, "WidgetList");

qwList::qwList(qgWidgetType type/*=QSWGT_LIST*/)
	: super_type(type)
	, _current(-1)
	, _scrlsize(22)
	, _height(18)
	, _border(6, 6)
{
	_insts.input = true;
	_insts.fill = true;

	_select.margin.Set(5, 0);
	_select.index = 0;
}

//
qwList::~qwList()
{
	ClearItems();

	kobj_unload(_scrl);
}

//
void qwList::OnInitialize()
{
	super_type::OnInitialize();

	_scrl = (qwScroll*)_shed->CreateControl(QGW_SCROLL, -1, tpl::Rect(0, 0, 0, 0), NULL);
	_scrl->SetParent(this);

	_select.res[0] = _shed->GetResource(QGWELM_LIST_SELECT_ACTIVE);
	_select.res[1] = _shed->GetResource(QGWELM_LIST_SELECT_INACTIVE);
}

//
void qwList::OnChangeFocus(bool focus)
{
	_isfocus = focus;
}

//
bool qwList::OnUpdate(float adv)
{
	bool boundrefresh = false;

	BuildBound();

	if (NeedRefresh())
	{
		// 스크롤 크기
		_scrl->SetBound(_bound.Width() - _scrlsize, 0, _scrlsize, _bound.Height());

		// 아이템 앵커
		_anchor.y = (_height - _text_info.size) / 2;

		if (_anchor.y < 0)
			_anchor.y = 0;

		//
		ResetRefresh();

		boundrefresh = true;
	}

	if (boundrefresh)
	{
		// 표시 영역
		_select.bound = _client.Deflate(_border.x, _border.y, _border.x + _scrlsize, _border.y);
		_blist = _select.bound.Deflate(_select.margin.x, _select.margin.y);

		// 스크롤 페이지 및 표시 위치
		if (_height > 0)
		{
			_scrl->SetPageSize(_blist.Height() / _height);
			_scrl->SetPosition(_current);
		}
	}

	_scrl->OnUpdate(adv);

	return true;
}

//
void qwList::OnDraw()
{
	if (CanFill())
		_shed->DrawFillRect(_client, _res[_status == QGWS_DISABLE ? QGWS_DISABLE : QGWS_NORMAL], _tex);

	if (_items.IsHave() /*&& _status != QGWS_DISABLE*/)
	{
		qbWidgetTextInfo ti(_text_info);
		const qbWidgetResource& res = _isfocus ? _select.res[0] : _select.res[1];

		tpl::Rect rttxt(_blist);
		kint height = _height;

		rttxt.top += _anchor.y;
		rttxt.bottom = rttxt.top + height;

		for (kint i = _scrl->GetPosition(); i < _items.Count(); i++)
		{
			if ((rttxt.bottom - _border.y) > _blist.bottom)
				break;

			Item* node = _items[i];

			bool isslt = false;

			if (!_canmulti)
			{
				if (i == _current)
					isslt = true;
			}
			else
			{
				if (_dragselect && ((i >= _current && i < _select.index) || (i <= _current && i > _select.index)))
					isslt = _items[_select.index]->select;
				else if (node->select)
					isslt = true;
			}

			if (node->str.IsHave())
			{
				if (!isslt)
					_shed->DrawAnchText(_font, node->str.Data(), rttxt, ti, 0);
				else
				{
					_shed->DrawFillRect(rttxt.Offset(0, -_anchor.y), res, _tex);
					_shed->DrawAnchText(_font, node->str.Data(), rttxt, ti, 0);
				}
			}

			rttxt.top += height;
			rttxt.bottom += height;
		}
	}

	_scrl->OnDraw();

	if (HasBorder())
		_shed->DrawEmptyRect(_client, _color_border);

	//
	qwCtrl::OnDraw();
}

//
void qwList::ClearItems()
{
	kForEach(Item* i, _items)
	{
		// 다른건 없고...
		delete i;
	}

	_items.Clear();

	//
	_current = -1;

	_scrl->SetCount(1);

	if (_ecb_select_changed)
		_ecb_select_changed(this, _current);
}

//
bool qwList::AddItem(const char* str, kpointer tag/*=NULL*/)
{
	k_return_value_if_fail(str, false);

	Item* node = new Item();
	node->str = str;
	node->tag = tag;
	_items.Add(node);

	_scrl->SetCount(_items.Count());

	return true;
}

//
bool qwList::InsertItem(kint nth, const char* str, kpointer tag/*=NULL*/)
{
	k_return_value_if_fail(str, false);

	Item* node = new Item();
	node->str = str;
	node->tag = tag;

	if (!_items.Insert(nth, node))
	{
		delete node;
		return false;
	}

	_scrl->SetCount(_items.Count());

	return true;
}

//
bool qwList::RemoveItem(kint nth)
{
	k_return_value_if_fail((ksize_t)nth < (ksize_t)_items.Count(), false);

	Item* node = _items[nth];
	delete node;

	_items.RemoveAt(nth);

	_scrl->SetCount(_items.Count());

	if (_current >= _items.Count())
	{
		_current = _items.Count() - 1;

		if (_ecb_select_changed)
			_ecb_select_changed(this, _current);
	}

	return true;
}

//
qwList::Item* qwList::GetItem(kint nth)
{
	return (ksize_t)nth < (ksize_t)_items.Count() ? _items[nth] : NULL;
}

//
const qbWidgetResource& qwList::GetResource(qgWidgetElement nth)
{
	if (nth == QGWELM_LIST_SELECT_ACTIVE)
		return _select.res[0];
	else if (nth == QGWELM_LIST_SELECT_INACTIVE)
		return _select.res[1];
	return super_type::GetResource(nth);
}

//
void qwList::SetSelectedIndex(kint nth)
{
	if (_items.IsEmpty())
		return;

	kint prev = _current;

	if (nth < 0)
		nth = 0;
	else if (nth >= _items.Count())
		nth = _items.Count() - 1;

	_current = nth;

	if (prev != nth)
	{
		if (_canmulti)
			_items[nth]->select = true;

		_select.index = nth;

		_scrl->SetPosition(nth);
	}

	//  if (_fn_sel_chgd)
	//      _fn_sel_chgd(this, HB_CAST_INT_TO_PTR(_current));
}

//
bool qwList::SetResource(qgWidgetElement nth, const qbWidgetResource& res)
{
	if (nth == QGWELM_LIST_SELECT_ACTIVE)
		_select.res[0] = res;
	else if (nth == QGWELM_LIST_SELECT_INACTIVE)
		_select.res[1] = res;
	else
		return super_type::SetResource(nth, res);
	return true;
}

//
bool qwList::OnMouseMove(kint x, kint y, const tpl::Point& relative, kushort state)
{
	if (!_scrl->OnMouseMove(x, y, relative, state))
		return false;

	// 다른 버튼은 안되고 왼쪽 버튼만!!
	if (state == QIMM_LEFT && !_dragging && _current >= 0 && _dragselect)
	{
		_dragging = true;

		if (_ecb_drag_item_enter)
			_ecb_drag_item_enter(this, _current, x, y);

		return false;
	}

	return true;
}

//
bool qwList::OnMouseDown(kint x, kint y, kushort button)
{
	if (!_scrl->OnMouseDown(x, y, button))
		return false;

	if (button == QIM_LEFT)
	{
		if (!_isfocus)
			_shed->SetFocus(this);

		if (_items.IsHave() && _select.bound.OnPoint(x, y))
		{
			kint scpos = _scrl->GetPosition();
			kint nth = scpos + (y - _blist.top) / _height;
			kint nmx = scpos + _scrl->GetPageSize();

			if (nth >= scpos && nth < _items.Count() && nth < nmx)
			{
				_dragselect = true;

				if (button & QIMM_DOUBLE)
				{
					if (_ecb_click)
						_ecb_click(this);

					return false;
				}

				//
				_current = nth;

				//
				qgStub* stub = qgRdh::Instance->GetStub();
				bool isshift = stub->IsKeyDown(QIK_SHIFT);
				bool isctrl = stub->IsKeyDown(QIK_CTRL);

				if (isshift)
					_select.index = nth;

				if (_canmulti)
				{
					Item* node = _items[nth];

					if (isshift && isctrl)
					{
						kint ns = K_MIN(_select.index, nth);
						kint ne = K_MAX(_select.index, nth);
						bool lastsel = _items[_select.index]->select;

						for (kint i = ns + 1; i < ne; i++)
							_items[i]->select = lastsel;

						node->select = true;

						_current = _select.index;
					}
					else if (isshift)
						node->select = !node->select;
					else if (isctrl)
					{
						kint ns = K_MIN(_select.index, nth);
						kint ne = K_MAX(_select.index, nth);

						for (kint i = ns; i < ns; i++)
							_items[i]->select = false;

						for (kint i = ne + 1; i < _items.Count(); i++)
							_items[i]->select = false;

						for (kint i = ns; i <= ne; i++)
							_items[i]->select = true;
					}
					else
					{
						for (kint i = 0; i < _items.Count(); i++)
							_items[i]->select = false;

						node->select = true;
					}
				}

				// 이거 재고해야겠음.. up에서 해야하지 않을까
				if (_ecb_select_changed)
					_ecb_select_changed(this, nth);

#if 0
				k_mesgf("cursel=%d, selpos=%d\n", _current, _select.index);
#endif
			}

			return false;
		}
	}

	return true;
}

//
bool qwList::OnMouseUp(kint x, kint y, kushort button)
{
	if (!_scrl->OnMouseUp(x, y, button))
		return false;

	if (_dragging)
	{
		if (_ecb_drag_item_leave)
			_ecb_drag_item_leave(this, _current, x, y);

		_dragging = false;
	}

	if (button == QIM_LEFT)
	{
		_dragselect = false;

		if (_current >= 0)
		{
			kint ns = K_MIN(_select.index, _current);
			kint ne = K_MAX(_select.index, _current);

			Item* node = _items[_select.index];

			for (kint i = ns + 1; i < ne; i++)
				_items[i]->select = node->select;

			if (_select.index != _current && _ecb_select_changed)
				_ecb_select_changed(this, _current);

			return false;
		}
	}

	return true;
}

//
bool qwList::OnMouseWheel(kshort delta)
{
	_scrl->Scroll(-delta);
	return false;
}

//
bool qwList::OnKeyDown(kbyte key, kbyte sub, kuint ch, bool repeat, kushort state)
{
	bool ret = true;

	if (key == QIK_PGUP)
	{
		_scrl->Scroll(-_scrl->GetPageSize());
		ret = false;
	}
	else if (key == QIK_PGDN)
	{
		_scrl->Scroll(+_scrl->GetPageSize());
		ret = false;
	}

	// 이거 항목 선택 & 스크롤도 만들어야됨

	return ret;
}

#endif	// _QG_ENABLE_WIDGET
